#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>

const int threads_num = 8; //进程个数
HANDLE Threads[threads_num];

// 声明需要的信号量
HANDLE chopstick[threads_num];
int nPID[threads_num];

// 奇数哲学家
void WINAPI Odd(LPVOID lpParameter)
{
    printf("奇数哲学家 %u 入座\n", GetCurrentThreadId());
    int *pID = (int*)lpParameter;
    while(true){
        WaitForSingleObject(chopstick[*pID], INFINITE);
        WaitForSingleObject(chopstick[(*pID+1)%threads_num], INFINITE);
        printf("哲学家: %d 开吃 ~ ,进程号：%u\n",*pID, GetCurrentThreadId());
        Sleep(1727);
        ReleaseMutex(chopstick[*pID]);
        ReleaseMutex(chopstick[(*pID+1)%threads_num]);
    }
}

// 偶数哲学家
void WINAPI Even(LPVOID lpParameter)
{
    printf("偶数哲学家 %u 入座\n", GetCurrentThreadId());
    int *pID = (int*)lpParameter;
    while(true){
        WaitForSingleObject(chopstick[(*pID+1)%threads_num], INFINITE);
        WaitForSingleObject(chopstick[*pID], INFINITE);
        printf("哲学家: %d 开吃 ~ ,进程号：%u\n",*pID, GetCurrentThreadId());
        Sleep(1113);
        ReleaseMutex(chopstick[(*pID+1)%threads_num]);
        ReleaseMutex(chopstick[*pID]);
    }
}

// 创建线程
void creatThreads()
{
    DWORD dwThreadID = 0;
    for (int i = 0; i < threads_num; i++)
    {
        if (i % 2 == 1)
        {
            if ((Threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Odd, &nPID[i], 0, &dwThreadID)) == NULL)
            {
                printf("奇数哲学家进程创建失败！\n");
                exit(0);
            }
            else
            {
                printf("奇数哲学家 %u 创建成功\n", dwThreadID);
            }
        }
        else
        {
            if ((Threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Even, &nPID[i], 0, &dwThreadID)) == NULL)
            {
                printf("偶数哲学家进程创建失败！\n");
                exit(0);
            }
            else
            {
                printf("偶数哲学家 %u 创建成功\n", dwThreadID);
            }
        }
    }
}

int main()
{
    // 哲学家进餐问题-初始化信号量
    printf("赵胜达的哲学家进餐问题解决方案：\n");
    char idname[20] = {0};
    for (int i=0;i<threads_num;i++){
        nPID[i]=i;
        itoa(i,idname,10);
        chopstick[i] = CreateMutex(NULL, FALSE, idname);
    }
    // 调用创建进程函数初始化读者和写着进程
    creatThreads();
    //确保线程间的相互等待
    WaitForMultipleObjects(threads_num, Threads, TRUE, INFINITE);
    return 0;
}